package com.tiger.log.core.processing.business;

import com.alibaba.fastjson2.JSON;
import com.alibaba.fastjson2.JSONWriter;
import com.tiger.log.common.annotation.business.form.ExcludeParams;
import com.tiger.log.common.annotation.business.form.PrimaryKey;
import com.tiger.log.common.entity.SysRecordLog;
import com.tiger.log.common.enums.ProcessType;
import com.tiger.log.common.exception.member.ErrorException;
import com.tiger.log.common.exception.member.InvalidPrimaryKeyException;
import org.aspectj.lang.ProceedingJoinPoint;
import org.aspectj.lang.reflect.MethodSignature;
import org.jetbrains.annotations.NotNull;
import org.springframework.stereotype.Component;
import java.lang.reflect.Method;
import java.lang.reflect.Parameter;
import java.util.*;

/**
 * @ClassName FormProcessing
 * @Description TODO
 * @Author huxuehao
 **/
@Component
public class FormProcessing {

    private final CommonProcessing commonProcessing;

    public FormProcessing(CommonProcessing commonProcessing) {
        this.commonProcessing = commonProcessing;
    }

    /**
     * 验证是否非法
     */
    public boolean isIllegal(ProceedingJoinPoint joinPoint) {
        return commonProcessing.isIllegal(joinPoint, ProcessType.FORM);
    }
    /**
     * 切入对象执行后的前置处理
     */
    public void proceedPreProcessing(@NotNull SysRecordLog recordLog, @NotNull ProceedingJoinPoint joinPoint) {
        fillRecordContent(recordLog, joinPoint);
        commonProcessing.fillRecordCollect(recordLog,joinPoint,ProcessType.FORM);
        commonProcessing.fillRecordRequest(recordLog);
    }

    /**
     * 切入对象执行后的后置处理
     */
    public void proceedPostProcessing(@NotNull SysRecordLog recordLog,Object res, boolean isCatch) {
        commonProcessing.fillRecordResult(recordLog, res, isCatch);
    }

    /**
     * 根据Content注解，从方法的参数中获取必要的内容填充SysRecordLog
     * CommonProcessing
     */
    public void fillRecordContent(@NotNull SysRecordLog recordLog, @NotNull ProceedingJoinPoint joinPoint) {
        String primaryKey = getPrimaryKey(joinPoint);
        /* 获取参数 */
        String[] paramsKey = ((MethodSignature) joinPoint.getSignature()).getParameterNames();
        Object[] paramsValue = joinPoint.getArgs();

        Map<String, Object> formMap = new LinkedHashMap<>();
        for (int i = 0; i < paramsValue.length; i++) {
            formMap.put(paramsKey[i], paramsValue[i]);
        }

        /* 排除参数*/
        excludeParams(joinPoint, formMap, primaryKey);

        /* 设置日志属性 */
        recordLog.setBusinessId(formMap.get(primaryKey).toString());
        recordLog.setBusinessData(JSON.toJSONString(formMap, JSONWriter.Feature.WriteMapNullValue));
    }

    /**
     * 验证参数中是否存在@PrimaryKey
     */
    private String getPrimaryKey(ProceedingJoinPoint joinPoint) {
        MethodSignature signature = (MethodSignature) joinPoint.getSignature();
        /* 获取参数 */
        Parameter[] parameters = signature.getMethod().getParameters();
        for (int i = 0; i <parameters.length; i++) {
            if ( parameters[i].isAnnotationPresent(PrimaryKey.class)) {
                /* 获取参数名 */
                return signature.getParameterNames()[i];
            }
        }
        throw new InvalidPrimaryKeyException();
    }

    /**
     * 排除参数
     */
    private void excludeParams(ProceedingJoinPoint joinPoint, Map<String, Object> formMap, String primaryKey) {
        Method method = ((MethodSignature) joinPoint.getSignature()).getMethod();
        if (method.isAnnotationPresent(ExcludeParams.class)) {
            ExcludeParams annotation = method.getAnnotation(ExcludeParams.class);
            List<String> exclude = Arrays.asList(annotation.exclude());
            if (exclude.size() == 0) {
                return;
            }
            if (exclude.contains(primaryKey)) {
                throw new ErrorException("@ExcludeParams中的值包含了primaryKey，该操作不合法");
            }
            formMap.keySet().removeIf(exclude::contains);
        }
    }
}
